<?php

/**
 * Maikuro CMS
 *
 * LICENSE:
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The license is bundled with this package in the file LICENSE.txt.
 * You may also obtain a copy of the License at this URL:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @copyright  Copyright (c) 2010, Jonathan Hedrén
 * @author     Jonathan Hedrén <jonathan.hedren@gmail.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

require_once 'entity/SiteEntity.php';

class SiteService extends AbstractDbEntityService
{
    protected $cacheIdentifier = 'sites_cache',
              $dbTable         = 'site',
              $entityClass     = 'SiteEntity';

    /**
     * Deletes a site.
     *
     * @param SiteEntity|integer $idOrEntity
     */
    public function delete($idOrEntity) {
        $id = ($idOrEntity instanceof SiteEntity) ? $idOrEntity->id : $idOrEntity;
        try {
            $this->pdo->beginTransaction();

            parent::delete($idOrEntity);
            $this->pdo->delete('administrator_permission', 'siteId = ?', $id);

            foreach ($this->fetchCustomFields($id) as $customField) {
                $this->pdo->delete('custom_field', 'id = ?', $customField->id);
            }

            $this->pdo->delete('site_custom_field', 'siteId = ?', $id);
            $this->pdo->delete('rewrite', 'siteId = ?', $id);

            $this->pdo->commit();
            
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

        /**
     *
     * @param integer $siteId
     * @return array
     */
    private function fetchCustomFields($siteId)
    {
        $result = $this->pdo->select('id', 'name', 'valueDisplayType', 'value')
                            ->from('custom_field')
                            ->innerJoin('site_custom_field', 'site_custom_field.customFieldId = custom_field.id')
                            ->where('site_custom_field.siteId = ?')
                            ->orderBy('id')
                            ->bindValues($siteId)
                            ->fetchAllAs('CustomFieldEntity');
        $customFields = array();
        foreach ($result as $customField) {
            $customFields[$customField->name] = $customField;
        }
        return $customFields;
    }

    /**
     * Fetches the site entities from the database.
     *
     * @return void
     */
    protected function fetchEntities()
    {
        parent::fetchEntities();
        foreach ($this->entities as $site) {
            $site->customFields = $this->fetchCustomFields($site->id);
        }
    }

    /**
     * Returns the site with the specified id or code.
     *
     * @param integer|string $id
     * @return SiteEntity
     */
    public function getSite($id)
    {
        if (is_int($id)) {
            if (!isset($this->entities[$id])) {
                return null;
            }
            return $this->entities[$id];
        } else {
            foreach ($this->entities as $site) {
                if ($site->code == $id) {
                    return $site;
                }
            }
        }
        return null;
    }

    /**
     * Returns all settings.
     *
     * @return array
     */
    public function getSites()
    {
        $sites = array();
        foreach ($this->entities as $site) {
            $sites[$site->id] = clone $site;
        }
        return $sites;
    }

    /**
     * Saves the site.
     *
     * @param SiteEntity $site
     * @return mixed
     */
    public function save(SiteEntity $site)
    {
        try {
            $this->pdo->beginTransaction();

            parent::save($site);

            $this->saveCustomFields($site);

            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     *
     * @param SiteEntity $site
     */
    private function saveCustomFields(SiteEntity $site)
    {
        $customFieldsToDelete = $this->fetchCustomFields($site->id);

        foreach ($site->customFields as $customField) {
            $columnsAndValues = $this->getColumnsAndValues("CustomFieldEntity", $customField);

            // If there is no id, insert a new row in the database...
            if ($customField->id === null) {
                $result = $this->pdo->insert('custom_field', $columnsAndValues);
                // If we've got no affected row there is a serious problem.
                if ($result < 1) {
                    throw new Exception('The database returned zero affected rows which indicates that no data was saved.');
                }

                $customField->id = $this->pdo->lastInsertId();
                $this->pdo->insert('site_custom_field', array('siteId' => $site->id, 'customFieldId' => $customField->id));
            } else {
                foreach ($customFieldsToDelete as $i => $currentCustomField)
                {
                    if ($currentCustomField->id == $customField->id) {
                        unset($customFieldsToDelete[$i]);
                        break;
                    }
                }

                // ...else update the existing row.
                $result = $this->pdo->update('custom_field', $columnsAndValues, 'id = ?', $customField->id);
            }
        }
        foreach ($customFieldsToDelete as $customFieldToDelete)
        {
            $this->pdo->delete('custom_field', 'id = ?', $customFieldToDelete->id);
            $this->pdo->delete('site_custom_field', 'customFieldId = ?', $customFieldToDelete->id);
        }
    }
}